home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997…eptember: Technology Seed / ATS Aug-Sept '97.toast / Navigation Services SDK / Examples / Sampler / Sampler ƒ / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  16.1 KB  |  648 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        file.c
  3.  
  4.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. #pragma segment DocSeg
  9.  
  10. #ifndef __STRINGS__
  11. #include <Strings.h>
  12. #endif
  13.  
  14. #ifndef __STDIO__
  15. #include <StdIO.h>
  16. #endif
  17.  
  18. #ifndef __FINDER__
  19. #include "Finder.h"
  20. #endif
  21.  
  22. #ifndef __NAVIGATION__
  23. #include "Navigation.h"
  24. #endif
  25.  
  26. #ifndef Common_Defs
  27. #include "Common.h"
  28. #endif
  29.  
  30. const long kPictHeaderSize = 512;
  31.  
  32. short ReadFile(Document* theDocument);
  33. short WriteFile(Document* theDocument);
  34. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec);
  35. pascal Boolean myFilterProc(AEDesc *theItem, void *info, NavCallBackUserData callBackUD);
  36.  
  37. extern Document* gDocumentList[kMaxDocumentCount];
  38.  
  39.  
  40. // *****************************************************************************
  41. // *
  42. // *    ReadFile()
  43. // *
  44. // *****************************************************************************
  45. short ReadFile(Document* theDocument)
  46. {    
  47.     long        count;
  48.     short        theResult;
  49.     char        buffer[256];
  50.     TextStyle    theStyle;
  51.  
  52.     SetCursor(*GetCursor(watchCursor));
  53.  
  54.     if (theDocument->theTE != NULL)
  55.         {
  56.         TESetSelect(0,(**(theDocument->theTE)).teLength,theDocument->theTE);
  57.         TEDelete(theDocument->theTE);
  58.  
  59.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  60.             return theResult;
  61.  
  62.         do    {
  63.             count = 256;
  64.             theResult = FSRead(theDocument->fRefNum,&count,&buffer);
  65.             TEInsert(&buffer,count,theDocument->theTE);
  66.             }
  67.         while (theResult == noErr);
  68.  
  69.         TESetSelect(0,32767,theDocument->theTE);
  70.         theStyle.tsFont = 21;
  71.         theStyle.tsSize = 12;
  72.         TESetStyle(doFont + doSize,&theStyle,true,theDocument->theTE);
  73.         TESetSelect(0,0,theDocument->theTE);
  74.         }
  75.     else
  76.         {
  77.         short     result = noErr;
  78.         long    fileSize = 0;
  79.         long    headerSize = 0;
  80.         long    pictSize = 0;
  81.  
  82.         SetCursor(*(Cursor**)GetCursor(watchCursor));
  83.         
  84.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  85.             return theResult;
  86.  
  87.         theResult = GetEOF(theDocument->fRefNum,&fileSize);
  88.         
  89.         theDocument->fPictLength = fileSize;
  90.         theDocument->fPictLength -= kPictHeaderSize;
  91.         theDocument->fPict = NewHandle(theDocument->fPictLength);
  92.         theDocument->fHeader = NewHandle(kPictHeaderSize);
  93.         if ((theDocument->fPict == NULL)||(theDocument->fPict == NULL))
  94.             {
  95.             SysBeep(5);
  96.             return memFullErr;
  97.             }
  98.         headerSize = kPictHeaderSize;
  99.         pictSize = theDocument->fPictLength;
  100.  
  101.         theResult = FSRead(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  102.         theResult = FSRead(theDocument->fRefNum,&pictSize,*theDocument->fPict);
  103.         }
  104.  
  105.     theDocument->dirty = false;
  106.  
  107.     return noErr;
  108. }
  109.  
  110.  
  111. // *****************************************************************************
  112. // *
  113. // *    WriteFile()
  114. // *
  115. // *****************************************************************************
  116. short WriteFile(Document* theDocument)
  117. {    
  118.     short    theResult;
  119.     long    length;
  120.     char*    bufPtr;
  121.  
  122.     SetCursor(*GetCursor(watchCursor));
  123.  
  124.     if (!theDocument->fRefNum)
  125.         return fnOpnErr;
  126.  
  127.     if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  128.         return theResult;
  129.  
  130.     if (theDocument->theTE != NULL)
  131.         {
  132.         length = (**(theDocument->theTE)).teLength;
  133.         bufPtr = *((**(theDocument->theTE)).hText);
  134.  
  135.         theResult = FSWrite(theDocument->fRefNum,&length,bufPtr);
  136.         if (theResult == noErr)
  137.             theResult = SetEOF(theDocument->fRefNum,length);
  138.         }
  139.     else
  140.         {
  141.         long headerSize = kPictHeaderSize;
  142.         long pictSize = theDocument->fPictLength;
  143.  
  144.         theResult = FSWrite(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  145.         if (theResult == noErr)
  146.             {
  147.             theResult = FSWrite(theDocument->fRefNum,&pictSize,*theDocument->fPict);    
  148.             if (theResult == noErr)
  149.                 theResult = SetEOF(theDocument->fRefNum,headerSize+pictSize);
  150.             }
  151.         }
  152.  
  153.     return theResult;
  154. }
  155.  
  156.  
  157. // *****************************************************************************
  158. // *
  159. // *    WriteNewFile()
  160. // *
  161. // *****************************************************************************
  162. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec)
  163. {    
  164.     short    theResult;
  165.     short    refNum = 0;
  166.  
  167.     SetCursor(*GetCursor(watchCursor));
  168.  
  169.     theResult = FSpOpenDF(newFileSpec,fsRdWrPerm,&refNum);
  170.     if (refNum != -1)
  171.         {
  172.         if (theResult = SetFPos(refNum,fsFromStart,0))
  173.             return(theResult);
  174.  
  175.         if (theDocument->theTE != NULL)
  176.             {
  177.             long    length;
  178.             char*    bufPtr;
  179.             length = (**(theDocument->theTE)).teLength;
  180.             bufPtr = *((**(theDocument->theTE)).hText);
  181.  
  182.             if (theResult = FSWrite(refNum,&length,bufPtr))
  183.                 return(theResult);
  184.  
  185.             theResult = SetEOF(refNum,length);
  186.             }
  187.         else
  188.             {
  189.             long headerSize = kPictHeaderSize;
  190.             long pictSize = theDocument->fPictLength;
  191.  
  192.             theResult = FSWrite(refNum,&headerSize,*theDocument->fHeader);
  193.             theResult = FSWrite(refNum,&pictSize,*theDocument->fPict);
  194.             
  195.             theResult = SetEOF(refNum,headerSize+pictSize);
  196.             }
  197.         theResult = FSClose(refNum);
  198.         }
  199.     return theResult;
  200. }
  201.  
  202.  
  203. // *****************************************************************************
  204. // *
  205. // *    DoNewDocument()
  206. // *
  207. // *****************************************************************************
  208. void DoNewDocument(Boolean newDocAsPICT)
  209. {    
  210.     Document* theDocument;
  211.     if (theDocument = NewDocument(newDocAsPICT))
  212.         ShowWindow(theDocument->theWindow);
  213. }
  214.  
  215.  
  216. // *****************************************************************************
  217. // *
  218. // *    DoOpenFile()
  219. // *
  220. // *****************************************************************************
  221. OSErr DoOpenFile(FSSpec* theFile, Boolean openAsPICT)
  222. {    
  223.     OSErr        result;
  224.     short        refNum;
  225.     Document*    theDocument;
  226.  
  227.     if (result = FSpOpenDF(theFile,fsRdWrPerm,&refNum))
  228.         return(result);
  229.  
  230.     if (theDocument = NewDocument(openAsPICT))
  231.         {
  232.         theDocument->fRefNum = refNum;
  233.         if (ReadFile(theDocument))
  234.             SysBeep(5);
  235.  
  236.         SetWTitle(theDocument->theWindow,theFile->name);
  237.         SizeDocWindow(theDocument);
  238.  
  239.         AdjustScrollBar(theDocument);
  240.         ShowWindow(theDocument->theWindow);    
  241.         }
  242.     else
  243.         {
  244.         SysBeep(1);
  245.         FSClose(refNum);
  246.         return(memFullErr);
  247.         }
  248.     return noErr;
  249. }
  250.  
  251.  
  252. // *****************************************************************************
  253. // *
  254. // *    myFilterProc()
  255. // *
  256. // *    If user choose "none" for 'open' resoure filtering, this routine could
  257. // *    affect the filter if used!
  258. // *
  259. // *****************************************************************************
  260. pascal Boolean myFilterProc(AEDesc* theItem, void* info, NavCallBackUserData /*callBackUD*/)
  261. {
  262.     OSErr                     theErr = noErr;
  263.     Boolean                 display = false;
  264.     NavFileOrFolderInfo*    theInfo;
  265.     
  266.     if (theItem->descriptorType == typeFSS)
  267.         {
  268.         theInfo = (NavFileOrFolderInfo*)info;    
  269.         if (((theInfo->isFolder) && (theInfo->visible)) ||
  270.             ((theInfo->u.fileInfo.finderInfo.fdFlags & kIsAlias) != 0))
  271.             display = true;            // item is a visible folder (normal or aliased)
  272.         else
  273.             switch (theInfo->u.fileInfo.finderInfo.fdType)
  274.                 {
  275.                 case 'TEXT':
  276.                 case 'PICT':
  277.                     display = true;
  278.                     break;
  279.                 default:
  280.                     display = false;
  281.                     break;
  282.                 }
  283.         }
  284.     return display;
  285. }
  286.  
  287.  
  288. // *****************************************************************************
  289. // *
  290. // *    myEventProc()    
  291. // *
  292. // *****************************************************************************
  293. pascal void myEventProc(const NavEventCallbackMessage callBackSelector, 
  294.                         NavCBRecPtr callBackParms, 
  295.                         NavCallBackUserData callBackUD)
  296. {
  297.     WindowPtr    pWindow = NULL;
  298.     Document**    docList;
  299.     Document*    theDoc = NULL;
  300.     short         index = 0;
  301.  
  302.     if ((callBackUD != 0)&&(callBackSelector == kNavCBEvent))
  303.         {
  304.         docList = (Document**)callBackUD;
  305.  
  306.         if (docList != NULL)
  307.             switch (callBackParms->event->what)
  308.                 {
  309.                 case nullEvent:
  310.                     break;
  311.                     
  312.                 case updateEvt:
  313.                     pWindow = (WindowPtr)callBackParms->event->message;
  314.                     theDoc = docList[index];
  315.                     if (theDoc != NULL)
  316.                         {
  317.                         while ((theDoc->theWindow != pWindow) && (docList[index] != NULL))
  318.                             {
  319.                             index++;
  320.                             theDoc = docList[index];
  321.                             }
  322.                         theDoc = docList[index];
  323.                         if (theDoc != NULL)
  324.                             UpdateWindow(theDoc);
  325.                         }
  326.                     break;
  327.  
  328.                 case activateEvt:
  329.                     break;
  330.  
  331.                 default:
  332.                     break;
  333.                 }
  334.         }
  335. }
  336.  
  337.  
  338. // *****************************************************************************
  339. // *
  340. // *    DoOpenDocumentTheOldWay()
  341. // *
  342. // *****************************************************************************
  343. OSErr DoOpenDocumentTheOldWay()
  344. {    
  345.     OSErr theErr = noErr;
  346.     //••
  347.     return theErr;
  348. }
  349.  
  350.  
  351. // *****************************************************************************
  352. // *
  353. // *    DoOpenDocument()
  354. // *
  355. // *****************************************************************************
  356. OSErr DoOpenDocument()
  357. {    
  358.     NavReplyRecord            theReply;
  359.     NavDialogOptions        dialogOptions;
  360.     OSErr                    theErr = noErr;
  361.     Handle                    openRsrc = NULL;
  362.     long                    count = 0;
  363.     NavEventProcUPP            eventProcUPP = NewNavEventProc(myEventProc);
  364.     NavObjectFilterProcUPP    filterProcUPP = NewNavObjectFilterProc(myFilterProc);
  365.     
  366.     // default behavior for browser and dialog:
  367.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  368.     dialogOptions.allowPreviews = true;
  369.  
  370.     GetIndString((unsigned char*)&dialogOptions.applicationName,FileStringsID,sApplicationName);
  371.     
  372.     openRsrc = GetResource(kOpenRsrcType,kOpenRsrcID);
  373.     if ((openRsrc != NULL)&&(ResError() == noErr))
  374.         HLock((Handle)openRsrc);
  375.  
  376.     dialogOptions.preferenceKey = kOpenPrefKey;
  377.  
  378.     theErr = NavGetFile(NULL,    // use system's default location
  379.                         &theReply,
  380.                         &dialogOptions,
  381.                         eventProcUPP,
  382.                         NULL,    // no custom previews
  383.                         (NavCallBackUserData)&gDocumentList,
  384.                         openRsrc,
  385.                         filterProcUPP);
  386.  
  387.     DisposeRoutineDescriptor(eventProcUPP);
  388.     DisposeRoutineDescriptor(filterProcUPP);
  389.  
  390.     if ((theReply.validRecord)&&(theErr == noErr))
  391.         {
  392.         // since we allow for multiple objects to be returned,
  393.         // grab the target FSSpecs from 'theReply.fileRef' list for opening:    
  394.         FSSpec        finalFSSpec;    
  395.         AEDesc         resultDesc;
  396.         FInfo        fileInfo;
  397.  
  398.         // in the case we didn't want built in translation:
  399.         if ((dialogOptions.dialogOptionFlags & kDontAutoTranslate) != 0)
  400.             if (theReply.translationNeeded)
  401.                 {
  402.                 // if we didn't want built in translation it was for the following reasons:
  403.                 //        1) we want to do it ourselves
  404.                 //        2) or we want to defer it    
  405.                 // things to remember if auto-translation is turned off:
  406.                 //         1) the AEDesc list contains the original file specs the user had chosen.
  407.                 //        2) the 'fileTranslation' field for each object that needs translation has filled in for you.
  408.                 
  409.                 // put your own code here to perform your own translation.
  410.                 // - or -
  411.                 // we can simply call this to perform the translation manually:
  412.                 theErr = NavTranslateFile(&theReply,kNavTranslateCopy);
  413.                 }
  414.  
  415.         // we are ready to open the document(s),
  416.         // grab information about each file for opening:
  417.         theErr = AECountItems(&(theReply.selection),&count);
  418.         for (long index=1;index<=count;index++)
  419.             {
  420.             resultDesc.dataHandle = 0L;
  421.             theErr = AEGetNthDesc(&(theReply.selection),index,typeFSS,NULL,&resultDesc);
  422.             if (theErr == noErr)
  423.                 {
  424.                 BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  425.             
  426.                 // decide if the doc we are opening is a 'PICT' or 'TEXT':
  427.                 theErr = FSpGetFInfo(&finalFSSpec,&fileInfo);
  428.                 if (theErr == noErr)
  429.                     {
  430.                     if (fileInfo.fdType == kFileType)
  431.                         DoOpenFile(&finalFSSpec,false);
  432.                     else
  433.                         if (fileInfo.fdType == kFileTypePICT)
  434.                             DoOpenFile(&finalFSSpec,true);
  435.                         else
  436.                             {
  437.                             // error:
  438.                             // if we got this far, the document is a type we can't open and
  439.                             // (most likely) built-in translation was turned off.
  440.                             // You can alert the user that this returned selection or file spec
  441.                             // needs translation.
  442.                             }
  443.                     }
  444.                 theErr = AEDisposeDesc(&resultDesc);
  445.                 }
  446.             }
  447.         theErr = NavDisposeReply(&theReply);    
  448.         }
  449.  
  450.     if (openRsrc != NULL)
  451.         {
  452.         HUnlock((Handle)openRsrc);
  453.         ReleaseResource((Handle)openRsrc);
  454.         }
  455.  
  456.     return theErr;
  457. }
  458.  
  459.  
  460. // *****************************************************************************
  461. // *
  462. // *    SaveACopyDocumentTheOldWay()
  463. // *
  464. // *****************************************************************************
  465. OSErr SaveACopyDocumentTheOldWay(Document* /*theDocument*/)
  466. {
  467.     //••
  468.     return noErr;
  469. }
  470.  
  471.  
  472. // *****************************************************************************
  473. // *
  474. // *    SaveACopyDocument()
  475. // *
  476. // *****************************************************************************
  477. OSErr SaveACopyDocument(Document* theDocument)
  478. {    
  479.     OSErr                theErr = noErr;
  480.     NavReplyRecord        theReply;
  481.     NavDialogOptions    dialogOptions;
  482.     NavEventProcUPP        eventProcUPP = NewNavEventProc(myEventProc);
  483.     Str255                docTitle;
  484.     OSType                fileTypeToSave;
  485.  
  486.     GetIndString((unsigned char*)&dialogOptions.applicationName,FileStringsID,sApplicationName);
  487.     
  488.     // default behavior for browser and dialog:
  489.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  490.  
  491.     GetWTitle(theDocument->theWindow,docTitle);
  492.     p2cstr((StringPtr)docTitle);
  493.     sprintf((char*)dialogOptions.savedFileName,(char*)"%s copy",docTitle);
  494.     c2pstr((Ptr)dialogOptions.savedFileName);
  495.         
  496.     if (theDocument->theTE != NULL)
  497.         fileTypeToSave = kFileType;
  498.     else
  499.         fileTypeToSave = kFileTypePICT;
  500.  
  501.     dialogOptions.preferenceKey = kSavePrefKey;
  502.  
  503.     theErr = NavPutFile(NULL,    // use system's default location
  504.                         &theReply,
  505.                         &dialogOptions,
  506.                         eventProcUPP,
  507.                         (NavCallBackUserData)&gDocumentList,
  508.                         fileTypeToSave,
  509.                         kFileCreator);
  510.  
  511.     DisposeRoutineDescriptor(eventProcUPP);
  512.  
  513.     if ((theReply.validRecord)&&(theErr == noErr))
  514.         {
  515.         FSSpec    finalFSSpec;    
  516.         AEDesc     resultDesc;    
  517.         resultDesc.dataHandle = 0L;
  518.         
  519.         // retrieve the returned selection:
  520.         // since only 1 selection is possible, we get the first AEDesc:
  521.         theErr = AEGetNthDesc(&(theReply.selection),1,typeFSS,NULL,&resultDesc);
  522.         if (theErr == noErr)
  523.             {
  524.             BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  525.  
  526.             if (theReply.replacing)
  527.                 theErr = FSpDelete(&finalFSSpec);
  528.             if (theErr == noErr)
  529.                 {
  530.                 theErr = FSpCreate(&finalFSSpec,kFileCreator,fileTypeToSave,smSystemScript);
  531.                 if (theErr == noErr)
  532.                     {
  533.                     theErr = WriteNewFile(theDocument,&finalFSSpec);    // use this document's data to write to our new copy
  534.                     if (theErr == noErr)
  535.                         {
  536.                         if (theReply.translationNeeded)
  537.                             {
  538.                             // translation is needed for file we are saving a copy of:
  539.                             if (theErr == noErr)
  540.                                 // when you save a copy, you should always "translate in place":
  541.                                 theErr = NavCompleteSave(&theReply,kNavTranslateInPlace);
  542.                             }
  543.                         }
  544.                     }
  545.                 }
  546.             else
  547.                 if (theErr == fBsyErr)
  548.                     DebugStr("\perror: file is busy, can't write");    //•• need alert
  549.             }
  550.         theErr = NavDisposeReply(&theReply);
  551.         }
  552.     
  553.     return theErr;
  554. }
  555.  
  556.  
  557. // *****************************************************************************
  558. // *
  559. // *    DoSaveDocument()
  560. // *
  561. // *****************************************************************************
  562. short DoSaveDocument(Document* theDocument)
  563. {
  564.     if (!theDocument)
  565.         return false;
  566.  
  567.     if (theDocument->fRefNum)
  568.         {
  569.         if (WriteFile(theDocument))
  570.             {
  571.             SysBeep(5);
  572.             return false;
  573.             }
  574.         else
  575.             theDocument->dirty = false;
  576.         return true;
  577.         }
  578.     else
  579.         {
  580.         //•• need SaveACopy replica here: return(SaveAsDocument(theDocument));
  581.         //•• also, these routines should return OSErr!
  582.         return true;
  583.         }
  584. }
  585.  
  586.  
  587. // *****************************************************************************
  588. // *
  589. // *    DoRevertDocument()
  590. // *
  591. // *****************************************************************************
  592. void DoRevertDocument(Document* theDocument)
  593. {    
  594.     if (!theDocument)
  595.         return;
  596.  
  597.     if (theDocument->fRefNum)
  598.         {
  599.         OSErr                         theErr = noErr;
  600.         NavEventProcUPP                eventProcUPP = NewNavEventProc(myEventProc);
  601.         NavAskDiscardChangesResult     reply;
  602.         Str255                         theName;
  603.  
  604.         GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  605.         theErr = NavAskDiscardChanges(    theName,
  606.                                         &reply,
  607.                                         eventProcUPP,
  608.                                         (NavCallBackUserData)&gDocumentList);
  609.         
  610.         DisposeRoutineDescriptor(eventProcUPP);
  611.  
  612.         switch (reply)
  613.             {
  614.             case askDiscardChanges:        
  615.                 if (ReadFile(theDocument))
  616.                     SysBeep(5);
  617.                 break;
  618.  
  619.             case askDiscardChangesCancel:
  620.                 break;
  621.             }
  622.         }
  623. }
  624.  
  625. // *****************************************************************************
  626. // *
  627. // *    DoRevertDocumentTheOldWay()
  628. // *
  629. // *****************************************************************************
  630. void DoRevertDocumentTheOldWay(Document* theDocument)
  631. {    
  632.     Str255 theName;
  633.  
  634.     if (!theDocument)
  635.         return;
  636.  
  637.     if (theDocument->fRefNum)
  638.         {
  639.         GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  640.         ParamText((ConstStr255Param)&theName,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  641.         if (Alert(idRevertALRT,0L) == 1)
  642.             if (ReadFile(theDocument))
  643.                 SysBeep(5);
  644.         }
  645. }
  646.  
  647.  
  648.